home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / src / haeberli / libgutil / invmap.c < prev    next >
C/C++ Source or Header  |  1994-08-01  |  7KB  |  286 lines

  1. /*
  2.  * Copyright 1992, 1993, 1994, Silicon Graphics, Inc.
  3.  * All Rights Reserved.
  4.  *
  5.  * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
  6.  * the contents of this file may not be disclosed to third parties, copied or
  7.  * duplicated in any form, in whole or in part, without the prior written
  8.  * permission of Silicon Graphics, Inc.
  9.  *
  10.  * RESTRICTED RIGHTS LEGEND:
  11.  * Use, duplication or disclosure by the Government is subject to restrictions
  12.  * as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
  13.  * and Computer Software clause at DFARS 252.227-7013, and/or in similar or
  14.  * successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
  15.  * rights reserved under the Copyright Laws of the United States.
  16.  */
  17. /*
  18.  *    invmap - 
  19.  *        Make and use inverse maps for dithering
  20.  *
  21.  *                Paul Haeberli - 1992
  22.  */
  23. #include "math.h"
  24. #include "invmap.h"
  25. #include "lum.h"
  26.  
  27. #define OFFSET_R    3
  28. #define OFFSET_G    2
  29. #define OFFSET_B    1
  30. #define OFFSET_A    0
  31.  
  32. static int ethresh;
  33.  
  34. ditthresh(t)
  35. int t;
  36. {
  37.     ethresh = t;
  38. }
  39.  
  40. static int getindex(m,or,og,ob)
  41. invmap *m;
  42. int or,og,ob;
  43. {
  44.     int i, r, g, b;
  45.     int dist, goodi, bestd;
  46.     int dr, dg, db;
  47.     unsigned char *rm, *gm, *bm;
  48.  
  49.     goodi = -1;
  50.     bestd = 200000;
  51.     if(m->bwmaps) {
  52.     rm = m->rmap;
  53.     for(i=0; i<m->maplen; i++) {
  54.         dist = or-(int)rm[i];
  55.         if(dist<0)
  56.          dist = -dist;
  57.         if(dist<bestd) {
  58.          goodi = i;
  59.          bestd = dist;
  60.         }
  61.     }
  62.     } else {
  63.     rm = m->rmap;
  64.     gm = m->gmap;
  65.     bm = m->bmap;
  66.     for(i=0; i<m->maplen; i++) {
  67.         dr = or-(int)rm[i];
  68.         dg = og-(int)gm[i];
  69.         db = ob-(int)bm[i];
  70.         dist = dr*dr+dg*dg+db*db;
  71.         if(dist<bestd) {
  72.          goodi = i;
  73.          bestd = dist;
  74.         }
  75.     }
  76.     }
  77.     return goodi;
  78. }
  79.  
  80. invmap *makeinvmap(rmap,gmap,bmap,maplen,tlevels)
  81. unsigned char *rmap, *gmap, *bmap;
  82. int maplen;
  83. int tlevels;
  84. {
  85.     invmap *m;
  86.     unsigned char *pptr;
  87.     int r, g, b, i;
  88.     int ir, ig, ib;
  89.     float div;
  90.     
  91.     m = (invmap *)malloc(sizeof(invmap));
  92.  
  93.     m->rmap = (unsigned char *)malloc(maplen*sizeof(char));
  94.     m->gmap = (unsigned char *)malloc(maplen*sizeof(char));
  95.     m->bmap = (unsigned char *)malloc(maplen*sizeof(char));
  96.     m->maplen = maplen;
  97.     bcopy(rmap,m->rmap,maplen);
  98.     bcopy(gmap,m->gmap,maplen);
  99.     bcopy(bmap,m->bmap,maplen);
  100.  
  101.     m->bwmaps = 1;
  102.     for(i=0; i<maplen; i++) {
  103.     if(rmap[i] != gmap[i] || gmap[i] != bmap[i]) {
  104.         m->bwmaps = 0;
  105.         break;
  106.     }
  107.     }
  108.   
  109.     if(m->bwmaps) {
  110.     m->tlevels = 256;
  111.     m->table = (unsigned char *)malloc(256*sizeof(char));
  112.     pptr = m->table;
  113.     for(i=0; i<256; i++) 
  114.         *pptr++ = getindex(m,i,i,i);
  115.     } else {
  116.     m->tlevels = tlevels;
  117.     m->table = (unsigned char *)malloc(tlevels*tlevels*tlevels*sizeof(char));
  118.     div = tlevels-1.0;
  119.     pptr = m->table;
  120.     for(b=0; b<tlevels; b++) {
  121.         ib = 255.0*b/div;
  122.         for(g=0; g<tlevels; g++) {
  123.         ig = 255.0*g/div;
  124.         for(r=0; r<tlevels; r++) {
  125.             ir = 255.0*r/div;
  126.             *pptr++ = getindex(m,ir,ig,ib);
  127.         }
  128.         }
  129.     }
  130.     }
  131.     return m;
  132. }
  133.  
  134. freeinvmap(map)
  135. invmap *map;
  136. {
  137.     free(map->table);
  138.     free(map->rmap);
  139.     free(map->gmap);
  140.     free(map->bmap);
  141.     free(map);
  142. }
  143.  
  144. static int buflen;
  145. static short *rerr;
  146. static short *gerr;
  147. static short *berr;
  148.  
  149. int ditarray(map,lbuf,obuf,xsize,ysize,dodither)
  150. invmap *map;
  151. unsigned long *lbuf;
  152. unsigned char *obuf;
  153. int xsize, ysize, dodither;
  154. {
  155.     int ir, ig, ib, y;
  156.     int i, l1, l2, sc, maxi;
  157.     unsigned char *base, *ipix;
  158.     int rwant, error;
  159.     int gwant;
  160.     int bwant;
  161.     int rerror, rnext;
  162.     int gerror, gnext;
  163.     int berror, bnext;
  164.     int index, n, nmalloc;
  165.     int outside;
  166.     unsigned char *rmap, *gmap, *bmap;
  167.  
  168.     base = map->table;
  169.     rmap = map->rmap;
  170.     gmap = map->gmap;
  171.     bmap = map->bmap;
  172.     ipix = (unsigned char *)lbuf;
  173.  
  174.     l1 = map->tlevels;
  175.     l2 = l1*l1;
  176.     sc = l1;
  177.     maxi = l1-1;
  178.  
  179.     if(dodither) {
  180.     nmalloc = xsize+1;
  181.     if(buflen<nmalloc) {
  182.         if(rerr) {
  183.         rerr = (short *)realloc(rerr,nmalloc*sizeof(short));
  184.         gerr = (short *)realloc(gerr,nmalloc*sizeof(short));
  185.         berr = (short *)realloc(berr,nmalloc*sizeof(short));
  186.         } else {
  187.         rerr = (short *)malloc(nmalloc*sizeof(short));
  188.         gerr = (short *)malloc(nmalloc*sizeof(short));
  189.         berr = (short *)malloc(nmalloc*sizeof(short));
  190.         }
  191.         buflen = nmalloc;
  192.     }
  193.     bzero(rerr,nmalloc*sizeof(short));
  194.     if(map->bwmaps) {
  195.         for(y=0; y<ysize; y++) {
  196.         rerror = 0;
  197.         rnext = rerr[0] = 0;
  198.         for(i=0; i<xsize; i++) {
  199.             rwant = ILUM(ipix[OFFSET_R],ipix[OFFSET_G],ipix[OFFSET_B]) 
  200.                 + rerror + rnext;
  201.             ipix += 4;
  202.             if(rwant>255) rwant = 255;
  203.             if(rwant<0)   rwant = 0;
  204.             index = *obuf++ = base[rwant];
  205.             error =  rwant-rmap[index];
  206.             if(error<ethresh && error>-ethresh) 
  207.             error = 0;
  208.             rerror = (3*error)/8;
  209.             rerr[i] += rerror;
  210.             rnext = rerr[i+1];
  211.             rerr[i+1] = error-2*rerror;
  212.         }
  213.         }
  214.     } else {
  215.         bzero(gerr,nmalloc*sizeof(short));
  216.         bzero(berr,nmalloc*sizeof(short));
  217.         for(y=0; y<ysize; y++) {
  218.         rerror = 0;
  219.         rnext = rerr[0] = 0;
  220.         gerror = 0;
  221.         gnext = gerr[0] = 0;
  222.         berror = 0;
  223.         bnext = berr[0] = 0;
  224.         for(i=0; i<xsize; i++) {
  225.             rwant = (int)ipix[OFFSET_R] + rerror + rnext;
  226.             gwant = (int)ipix[OFFSET_G] + gerror + gnext;
  227.             bwant = (int)ipix[OFFSET_B] + berror + bnext;
  228.             ipix += 4;
  229.             if(rwant>255) rwant = 255;
  230.             if(rwant<0)   rwant = 0;
  231.             if(gwant>255) gwant = 255;
  232.             if(gwant<0)   gwant = 0;
  233.             if(bwant>255) bwant = 255;
  234.             if(bwant<0)   bwant = 0;
  235.             ir = (rwant*sc)>>8;
  236.             ig = (gwant*sc)>>8;
  237.             ib = (bwant*sc)>>8;
  238.             index = *obuf++ = base[(ir+ig*l1+ib*l2)];
  239.  
  240.             error =  rwant-rmap[index];
  241.             if(error<ethresh && error>-ethresh) 
  242.             error = 0;
  243.             rerror = (3*error)/8;
  244.             rerr[i] += rerror;
  245.             rnext = rerr[i+1];
  246.             rerr[i+1] = error-2*rerror;
  247.  
  248.             error =  gwant-gmap[index];
  249.             if(error<ethresh && error>-ethresh) 
  250.             error = 0;
  251.             gerror = (3*error)/8;
  252.             gerr[i] += gerror;
  253.             gnext = gerr[i+1];
  254.             gerr[i+1] = error-2*gerror;
  255.  
  256.             error =  bwant-bmap[index];
  257.             if(error<ethresh && error>-ethresh) 
  258.             error = 0;
  259.             gerror = (3*error)/8;
  260.             berror = (3*error)/8;
  261.             berr[i] += berror;
  262.             bnext = berr[i+1];
  263.             berr[i+1] = error-2*berror;
  264.         }
  265.         }
  266.     }
  267.     } else {
  268.     n = xsize*ysize;
  269.     if(map->bwmaps) {
  270.         while(n--) {
  271.         *obuf++ = base[ILUM(ipix[OFFSET_R],
  272.                     ipix[OFFSET_G],ipix[OFFSET_B])];
  273.         ipix += 4;
  274.         }
  275.     } else {
  276.         while(n--) {
  277.         ir =  (ipix[OFFSET_R]*sc)/256;
  278.         ig =  (ipix[OFFSET_G]*sc)/256;
  279.         ib =  (ipix[OFFSET_B]*sc)/256;
  280.         *obuf++ = base[(ir+ig*l1+ib*l2)];
  281.         ipix += 4;
  282.         }
  283.     }
  284.     }
  285. }
  286.